#ifndef SINGLETON_H
#define SINGLETON_H

#include <memory>
#include <mutex>
#include <iostream>
using namespace std;

template <class T>
class Singleton {
protected:
    Singleton() = default;
    Singleton(const Singleton<T>&) = delete;
    Singleton& operator=(const Singleton<T>& st) = delete;
    static std::shared_ptr<T> _instance;
public:
    static std::shared_ptr<T> GetInstance()
    {
        static std::once_flag s_flag;
        std::call_once(s_flag, [&]()
        {
            _instance = shared_ptr<T>(new T);
        });
        return _instance;
    }

    void PrintAddress()
    {
        std::cout << _instance.get() << endl;
    }

    ~Singleton()
    {
        std::cout << "~Singleton()" << std::endl;
    }
};

template <class T>
std::shared_ptr<T> Singleton<T>::_instance = nullptr;


//template <class T>
//class Singleton1 {
//protected:
//    Singleton1() = default;
//    Singleton1(const Singleton1<T>&) = delete;
//    Singleton1& operator=(const Singleton1<T>& st) = delete;

//public:
//    static Singleton<T> GetInstance()
//    {
//        static Singleton<T> _instance;

//        return _instance;
//    }
//};
#endif // SINGLETON_H
